package com.ruoyi.common.websocket;

import cn.hutool.core.util.ArrayUtil;
import com.alibaba.fastjson2.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.ConcurrentLinkedQueue;

/**
 * @author ab785
 * createTime: 2021-12-3.
 * description: websocket服务
 */
@Slf4j
@Component
@ServerEndpoint("/ws/msg/{userName}")
public class MessageEndpoint {

    /**
     * 当前连接
     */
    private Session session;

    /**
     * 用户名，用于定位发送
     */
    private String userName;

    /**
     * 已连接的列表
     */
    private static ConcurrentLinkedQueue<MessageEndpoint> clientList = new ConcurrentLinkedQueue<>();

    @OnOpen
    public void onOpen(Session session, @PathParam("userName") String userName) {
        this.session = session;
        this.userName = userName;
        //添加记录
        clientList.add(this);

        log.info("================用户 {} 已连接，当前连接数：{}=======================", userName, clientList.size());

        //连接时发送一次 测试连接
        //SocketMessageNotifyData notifyData = SocketMessageNotifyData.createSuccessInstance("提示", "websocket连接已打开");
        //notifyData.setDuration(3000L);
        //SocketMessageVo<SocketMessageNotifyData> connectMsg = SocketMessageVo.createNotifyVo(notifyData);
        //sendMessageToSession(session, JSON.toJSONString(connectMsg));
    }

    @OnMessage
    public void onMessage(Session session, String message) {

        //接收到心跳时直接回传到前端
        SocketMessageVo msgVo = JSON.parseObject(message, SocketMessageVo.class);
        if (SocketMessageVo.EventType.HEART.equals(msgVo.getEventType())) {
            sendMessageToSession(session, message);
        }
    }

    @OnClose
    public void onClose() {
        //移除
        clientList.remove(this);

        log.info("================用户 {} 失去连接，当前连接数：{}=======================", userName, clientList.size());
    }

    @OnError
    public void onError(Throwable error) {
        log.error("socket异常", error);
    }

    //发送消息方法========================================================================================

    /**
     * 向用户发送消息
     */
    public void sendMessageToUsers(SocketMessageVo msgVo, String... userNames) {
        for (String userName : userNames) {
            for (MessageEndpoint client : clientList) {
                if (client.userName.equals(userName)) {
                    sendMessageToSession(client.session, JSON.toJSONString(msgVo));
                }
            }
        }
    }

    /**
     * 向用户发送消息
     */
    public void sendMessageToUsers(SocketMessageVo msgVo, List<String> userNames) {
        sendMessageToUsers(msgVo, ArrayUtil.toArray(userNames, String.class));
    }

    /**
     * 向用户发送消息
     */
    public void sendMessageToAllUsers(SocketMessageVo msgVo) {
        for (MessageEndpoint client : clientList) {
            sendMessageToSession(client.session, JSON.toJSONString(msgVo));
        }
    }

    /**
     * 向session 发送消息 发送消息实体
     */
    private void sendMessageToSession(Session session, String jsonText) {
        try {
            session.getBasicRemote().sendText(jsonText);
        } catch (IOException e) {
            log.error("发送消息异常", e);
        }
    }

}
